package cn.axj.crypt.secret.implement;

import cn.axj.crypt.constant.AlgorithmConstant;
import cn.axj.crypt.secret.config.AesKeyConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import cn.axj.crypt.secret.BaseAlgorithmHttpInputMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;

/**
 * @author aoxiaojun
 * @date 2020/12/11 17:08
 **/
@Component
public class AesAlgorithmHttpInputMessage extends BaseAlgorithmHttpInputMessage {


    @Resource
    private AesKeyConfig aesKeyConfig;

    @Override
    public String getBinding() {
        return AlgorithmConstant.AES;
    }



    @Override
    public String decrypt(String content) throws Exception {
        return decrypt(content,aesKey,ivVal);
    }


    @Override
    public String encrypt(String content) throws Exception{
        return encrypt(content, aesKey, ivVal);
    }


    private static String aesKey;
    private static String ivVal;


    @Autowired
    public void setAesKey() {
        AesAlgorithmHttpInputMessage.aesKey = aesKeyConfig.getKey();
    }
    @Autowired
    public void setIvVal() {
        AesAlgorithmHttpInputMessage.ivVal = aesKeyConfig.getIv();
    }

    /**
     * 算法名
     */
    private static final String KEY_ALGORITHM = "AES";

    /**
     * 加解密算法/模式/填充方式
     * ECB模式只用密钥即可对数据进行加密解密，CBC模式需要添加一个参数iv
     */
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";


    /**
     * 生成密匙
     * @param aesKey aeskey
     * @return byte
     */
    private byte[] generateKey(String aesKey) {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        return aesKey.getBytes();
    }



    private AlgorithmParameters generateIV(String ivVal) throws Exception{
        byte[] iv = ivVal.getBytes();
        AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_ALGORITHM);
        params.init(new IvParameterSpec(iv));
        return params;

    }


    /**
     * 转化成JAVA的密钥格式
     * @param keyBytes keyBytes
     * @return Key
     */
    private Key convertToKey(byte[] keyBytes) {
        return new SecretKeySpec(keyBytes,KEY_ALGORITHM);
    }



    //加密
    private String encrypt(String plainText, String aesKey, String ivVal) throws Exception {
        byte[] data=plainText.getBytes();
        AlgorithmParameters iv = generateIV(ivVal);
        byte[] keyBytes = generateKey(aesKey);
        //转化为密钥
        Key key = convertToKey(keyBytes);
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        //设置为加密模式
        cipher.init(Cipher.ENCRYPT_MODE, key,iv);
        byte[] encryptData= cipher.doFinal(data);
        return bytesToHexString(encryptData);
    }


    //解密
    private String decrypt(String encryptedStr, String aesKey, String ivVal) throws Exception{
        byte[] encryptedData = hexStringToByte(encryptedStr);
        byte[] keyBytes = generateKey(aesKey);
        Key key = convertToKey(keyBytes);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        AlgorithmParameters iv = generateIV(ivVal);
        //设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, key,iv);
        byte[] decryptData = cipher.doFinal(encryptedData);
        return new String(decryptData);
    }



    /**
     * 十六进制字符串转换成数组
     * @param hex
     * @return
     */
    private byte[] hexStringToByte(String hex) {
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }



    private byte toByte(char c) {
        return (byte) "0123456789abcdef".indexOf(c);

    }



    /**
     * 把字节数组转换成16进制字符串
     * @param bArray
     * @return
     */
    private String bytesToHexString(byte[] bArray) {
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (byte b : bArray) {
            sTemp = Integer.toHexString(0xFF & b);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toLowerCase());
        }
        return sb.toString();

    }


    public static void main(String[] args) {
        AesAlgorithmHttpInputMessage aesAlgorithmHttpInputMessage = new AesAlgorithmHttpInputMessage();
        //明文
        String plainTextString = "你好吗？我是bob";
        System.out.println("明文 : "+plainTextString);
        String aesKey="S9u978Q31NGPGc5H";
        String ivVal="X83yESM9iShLxfwS";
        try {
            //进行加密
            String encryptedData = aesAlgorithmHttpInputMessage.encrypt(plainTextString, aesKey,ivVal);
            //输出加密后的数据
            System.out.println("加密后的数据 : ");
            System.out.println(encryptedData);
            System.out.println();
            String s = "cf5e0a8898d2156f196fce2475ff80d13e5705684ca07ebdcd49ea8d495e9b075ef133a1bdaa9aa15f250998ecc9554b85502c53fb599cb964f4ea1db517c71b60f7f68bca8cf2bc21dc21e7d8f67d2f3a16a19307eadd6368b692a113125b8326245e804e5f8d1feaba1ceb69118f364ec3cb8a30c18b56b523a0e9c1d51eb66145b84ef11e968caa4fd9e1e7ab6862db5989f6e2fe2b0c1927433925d6335ff3b1576cc6e22b140fd9b28a3bbc571c88464c3931bed9492d97cebfda816466ab58c0001805ac4cbcd0e46c8b355ab64ad939c4dd8617edb558a645f3be86d33782eaa24e4573528701a34f1b244a483c400a2e854c7cf935244e3f676660cadf1d9679c0c85592e52946da2548376a483ee80cfb441106f09b7a2d23e6a91c1914cac84cea28d040ae9f62d292bdbb42b21a08d2014759697c8395d154bb018578bf30c5b81cadcb99ab131f253ae49070a3bb0660d00b022397d42ec60524b79ce83a5917841ffc00dcd91842019c9c5775a97bc2da8d7da6bf48c8a37385e86703c5720ecf1d801d4c9c936409a6fa1b517ed8542972c40438f786dc02ea6579ccf5cc86b79b08a1cf16d8bc0a57a8895dce6f18c91746daaae19510487529b6065d93050845a758e8076ee54095d9caa515d10ef8b972f18529a583933cd8bd7b521dd69869266509586965b4f4a4180fbbbd021fe2bbaf9e14e3f0f52ea23623c2c460199d4933a9b48e2e8bd308d0a3c7b7c264a11644c8b329d23bd1ecf95a0a5e942f7d17e370a50a6acfd45ae9bffcc5227c9a097a55c99bb00fb5eb02b3de8edf14257ca5468a61a43e502cb643eb2ccc45ea7d230fa724cf5d09245430dc867265f9890017e2a9d9297d2bdc5366ecad01ac6972df78e34f6ead1e8f7fece61d8f7657e9e394b848ea13eab0d0c31c4b969201cf950a264468bb8ac5316cc9376cefc64c43c12cd60e4203994b194f3b15503abdb8b80015bef60faa64d1b855d1a83cfd214aa838a25654c8aa4536968108f17b1dc76cf49f04635cf712fa0a28ea536c13cd465ead43254e1f165b19ca63782081c485d9b1def8cea2400d18e764c8672791d6b9a6f655256c7bc24cc7255877b65975959ff837583a8f3e21e09a937e9bfa147c062170b37a8aa6236b0f774008c82b53b03a81f062d69867e7cd03b774457016cd9047d726f48fbb42012bf94d5cd0d548dcafb189526404235d2036ffb0cbab0b981fa69f214494924f71da0a03a46eebe103cb28493eccf27b2f186789c7c162c62e48e0ea985fd9015326ada2195bec936306c1a9aa68afa78b0cffdd52f6cdad35f309497f6a9851273ab61169d3411f88cb17b56f6fcfb8bfba319fe4efe588594aeac0fc8bb504d73329ba3b6276f60126dc1f55cfe18872ae27b485b475739793e2ccd4c38592dedc5de905a15b8fcd8f2ddc6583742b37dbdd0a10a656524ae6c4a1f2f795467131b7cda2d09ce6e9e53c571bba00a8940aab5f8ca08203090d0d6130b364d892a7fa1984e342105958658c00da6be3c61c7a3e0b37b384fe3d30ed16ff6c4037a709840358794e309350a572a37ca2dfec7166cd346be8a0d16dfa776709607e505c078e46d569c7a454fb1569a4a816888944074012479b313bbf91f9d675fbd9b50855df34d77c99975a62c879266242c14d194c2105ff25a5a1e90062d5e48312b3915fb6944ad0ca1e735677282a847e0bbaaaffd86cdf9a03f9a57b0da79eb5e745b12a12dd187b632ccac48c97b6ef45b9b174bbaa4e5c307c995f26fa812daa9372b7f4ced8e08606ed1c872de4997cd8e6dc27";
            String data = aesAlgorithmHttpInputMessage.decrypt(s, aesKey,ivVal);
            System.out.println("解密得到的数据 : " + data);
            JSONObject jsonObject = JSON.parseObject(data);
            System.out.println(jsonObject);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
